<template>
    <view class="sign-components">
        <view class="clear-content">
            <view
                class="clear-btn"
                @click="clear()"
            >
                <image
                    class="clear-icon"
                    src="@/static/image/icon_clear.png"
                    mode="aspectFill"
                /> 清空
            </view>
        </view>
        <canvas
            class="mycanvas"
            canvas-id="mycanvasId"
            @touchstart="touchstart"
            @touchmove="touchmove"
            @touchend="touchend"
        />
        <view class="footer">
            <view
                class="right"
                @click="close"
            >
                取消
            </view>
            <view
                class="left"
                @click="finish"
            >
                确定
            </view>
        </view>
    </view>
</template>

<script setup name="Sign">
    import { ref, reactive, inject, onMounted, getCurrentInstance } from 'vue';

    const props = defineProps({
        // 签名图片上传携带额外参数
        extData: {
            type: Object,
            default: () => ({})
        },
        /* 系统上传接口地址
            https://yq.zsacloud.zhonshian.com/dev-asian-api/fileupload/file/uploadImages
            https://yq.zsacloud.zhonshian.com/zsaImg/fastDfs/uploadFast
        */
        uploadUrl: {
            type: String,
            default: import.meta.env.VITE_IMG_UPLOAD_URL + '/fastDfs/uploadFast',
        }
    });

    const emit = defineEmits(['cancel', 'confirm']);

    const toast = inject('$toast');

    let state = reactive({
        ctx: '', //绘图图像
        points: [] ,//路径点集合
        points1: []
    });

    // 获取签名组件实例
    const instance = getCurrentInstance();

    onMounted(() => {
        state.ctx = uni.createCanvasContext("mycanvasId", instance); //创建绘图对象
        //设置画笔样式
        state.ctx.lineWidth = 2;
        state.ctx.strokeStyle = '#0679FF';
        state.ctx.lineCap = "round";
        state.ctx.lineJoin = "round";
    });

    const close = () => {
        emit('cancel');
    };

    //触摸开始，获取到起点
    const touchstart = (e) => {
        let startX = e.changedTouches[0].x;
        let startY = e.changedTouches[0].y;
        let startPoint = {
            X: startX,
            Y: startY
        };

        /* **************************************************
            #由于uni对canvas的实现有所不同，这里需要把起点存起来
            * **************************************************/

        state.points.push(startPoint);
        state.points1.push(startPoint);
        //每次触摸开始，开启新的路径
        state.ctx.beginPath();
    };

    //触摸移动，获取到路径点
    const touchmove = (e) => {
        let moveX = e.changedTouches[0].x;
        let moveY = e.changedTouches[0].y;
        let movePoint = {
            X: moveX,
            Y: moveY
        };
        state.points.push(movePoint); //存点
        state.points1.push(movePoint); //存点
        let len = state.points.length;
        if (len >= 2) {
            draw(); //绘制路径
        }
    };

    // 触摸结束，将未绘制的点清空防止对后续路径产生干扰
    const touchend = () => {
        state.points = [];
    };

    /* ***********************************************
    #   绘制笔迹
    #   1.为保证笔迹实时显示，必须在移动的同时绘制笔迹
    #   2.为保证笔迹连续，每次从路径集合中区两个点作为起点（moveTo）和终点(lineTo)
    #   3.将上一次的终点作为下一次绘制的起点（即清除第一个点）
    ************************************************ */
    const draw = () => {
        let point1 = state.points[0];
        let point2 = state.points[1];
        state.points.shift();
        state.ctx.moveTo(point1.X, point1.Y);
        state.ctx.lineTo(point2.X, point2.Y);
        state.ctx.stroke();
        state.ctx.draw(true);
    };

    //清空画布
    const clear = () => {
        uni.getSystemInfo({
            success: (res) => {
                state.points = [];
                state.points1 = [];
                let canvasw = res.windowWidth;
                let canvash = res.windowHeight;
                state.ctx.clearRect(0, 0, canvasw, canvash);
                state.ctx.draw(true);
            },
        });
    };

    //完成绘画并保存到本地
    const finish = () => {
        if (state.points1.length <= 0) {
            toast('请签名后提交');
            return false;
        }
        uni.showLoading({
            title: '保存中'
        });
        uni.canvasToTempFilePath({
            canvasId: 'mycanvasId',
            fileType: 'jpeg',
            success: (res) => {
                let path = res.tempFilePath;
                // #ifdef H5
                path = dataURLtoFile(path, new Date().getTime() + '.jpeg');
                // #endif
                upLoadImage(path, (img) => {
                    uni.hideLoading();
                    emit('confirm', img);
                }, (err) => {
                    uni.hideLoading();
                });
            },
            fail: (e) => {
                console.log(e, 'fail');
            }
        }, instance);
    };

    const upLoadImage = (file, success, fail) => {
        let obj = {
            url: props.uploadUrl,
            name: 'file',
            formData: Object.assign({groupType: 'personalInfo'}, props.extData),
            success: (res) => {
                let data = JSON.parse(res.data);
                if (data.code == 10000) {
                    success(data.data);
                } else {
                    fail(data);
                    toast(data.msg);
                }
            },
            fail: (res) => {
                fail(res);
            }
        };

        //#ifdef MP-WEIXIN
        obj.filePath = file;
        //#endif

        //#ifdef H5
        obj.file = file;
        //#endif

        uni.uploadFile(obj);
    };

    const dataURLtoFile = (dataurl, filename) => {
        //64转file
        var arr = dataurl.split(","),
            mime = arr[0].match(/:(.*?);/)[1],
            bstr = atob(arr[1]),
            n = bstr.length,
            u8arr = new Uint8Array(n);
        while (n--) {
            u8arr[n] = bstr.charCodeAt(n);
        }
        return new File([u8arr], filename, {
            type: mime
        });
    };
</script>

<style scoped lang="less">
    .sign-components {
        width: 100%;
        height: 100%;
        background: #fff;
        position: relative;
    }

    .clear-content {
        height: 80rpx;
        padding: 0 30rpx;
        // position: absolute;
        // top: 0;
        // right: 0;
        // z-index: 999;
        display: flex;
        justify-content: flex-end;
        align-items: center;
        .clear-btn{
            height: 100%;
            display: flex;
            justify-content: flex-end;
            align-items: center;
            color: #FF490F;
        }
    }

    .clear-icon {
        width: 35rpx;
        height: 35rpx;
        margin-right: 20rpx;
    }

    .title {
        height: 50rpx;
        line-height: 50rpx;
        font-size: 16px;
    }

    .mycanvas {
        width: 100%;
        height: calc(100% - 230rpx);
        background-color: #fff;
    }

    .footer {
        font-size: 16px;
        height: 150rpx;
        display: flex;
        justify-content: space-around;
        align-items: center;
        background: #fff;
    }

    .left,
    .right {
        line-height: 100rpx;
        height: 100rpx;
        width: 250rpx;
        text-align: center;
        font-weight: bold;
        color: white;
        border-radius: 5rpx;
    }

    .left {
        background: #007AFF;
    }

    .right {
        background: orange;
    }
</style>
